package cn.fintecher.pangolin.service.business.service;

import cn.fintecher.pangolin.common.enums.FlowType;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.mysql.FlowConfiguration;
import cn.fintecher.pangolin.entity.mysql.FlowNodeConfig;
import cn.fintecher.pangolin.entity.mysql.QFlowConfiguration;
import cn.fintecher.pangolin.service.business.model.request.CreateConfigFlowRequest;
import cn.fintecher.pangolin.service.business.model.request.FlowNodeModel;
import cn.fintecher.pangolin.service.business.model.request.ModifyFlowConfigRequest;
import cn.fintecher.pangolin.service.business.repository.jparepository.ApproveUserRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.FlowConfigurationRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.FlowNodeRepository;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class FlowConfigurationService {

    @Autowired
    private FlowConfigurationRepository flowConfigurationRepository;

    @Autowired
    private FlowNodeRepository flowNodeRepository;

    @Autowired
    private ApproveUserRepository approveUserRepository;

    /**
     * @Author wangxiangdong
     * @Description 创建流程配置
     * @Date 2019/9/26 9:32
     **/
    public void createFlowConfig(CreateConfigFlowRequest request, UserModel userModel){
        checkApproveFlowConfig(request.getFlowType(),null);
        FlowConfiguration flowConfiguration = new FlowConfiguration();
        flowConfiguration.setConfigName(request.getConfigName());
        flowConfiguration.setFlowType(request.getFlowType());
        flowConfiguration.setOperator(userModel.getId());
        flowConfiguration.setOperatorTime(ZWDateUtil.getNowDate());
        flowConfiguration.setFlowNode(createFlowNode(request.getFlowNodes()));
        flowConfigurationRepository.save(flowConfiguration);
    }

    private Set<FlowNodeConfig> createFlowNode(List<FlowNodeModel> flowNodeModelList){
        Set<FlowNodeConfig> flowNodeSet = new HashSet<>();
        for(int i=0;i<flowNodeModelList.size();i++){
            FlowNodeConfig flowNode = new FlowNodeConfig();
            flowNode.setApproverConfigs(flowNodeModelList.get(i).getApproverConfigs());
            flowNode.setNodeValue(i);
            flowNodeSet.add(flowNode);
        }
        return  flowNodeSet;
    };

    /**
     * @Author wangxiangdong
     * @Description 创建流程配置
     * @Date 2019/9/26 9:32
     **/
    @Transactional
    public void modifyFlowConfig(ModifyFlowConfigRequest modifyFlowConfigRequest, UserModel userModel){
        FlowConfiguration flowConfiguration = flowConfigurationRepository.findById(modifyFlowConfigRequest.getId()).
                orElseThrow(()->new BadRequestException(null, "configFlow","configFlow.is.not.exist"));
        checkApproveFlowConfig(modifyFlowConfigRequest.getFlowType(),modifyFlowConfigRequest.getId());
        flowConfiguration.setOperator(userModel.getId());
        flowConfiguration.setOperatorTime(ZWDateUtil.getNowDate());
        flowConfiguration.setConfigName(modifyFlowConfigRequest.getConfigName());
        flowConfiguration.setFlowType(modifyFlowConfigRequest.getFlowType());
        flowConfiguration.getFlowNode().forEach(model->{
            approveUserRepository.deleteAll(model.getApproverConfigs());
        });
        flowNodeRepository.deleteAll(flowConfiguration.getFlowNode());
        flowConfiguration.setFlowNode(createFlowNode(modifyFlowConfigRequest.getFlowNodes()));
        flowConfigurationRepository.save(flowConfiguration);
    }

    /**
     * 校验是否为唯一流程
     */
    public void checkApproveFlowConfig(FlowType flowType,String id ){
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(QFlowConfiguration.flowConfiguration.flowType.eq(flowType));
        if(StringUtils.isNotBlank(id)){
            booleanBuilder.and(QFlowConfiguration.flowConfiguration.id.ne(id));
        }
        Iterable<FlowConfiguration> iterable = flowConfigurationRepository.findAll(booleanBuilder);
        if(iterable.iterator().hasNext()){
            throw new BadRequestException(null, "configFlow", "configFlow.has.exist.approvalType");
        }
    }

    /**
     * @Author wangxiangdong
     * @Description 根据流程类别查询流程
     * @Date 2019/9/19 15:54
     **/
    public FlowConfiguration findFlowConfigByType(FlowType flowType) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(QFlowConfiguration.flowConfiguration.flowType.eq(flowType));
        Iterable<FlowConfiguration> iterable = flowConfigurationRepository.findAll(booleanBuilder);
        if(iterable.iterator().hasNext()){
            return iterable.iterator().next();
        }else{
            throw new BadRequestException(null,"findFlowConfigByType","flow.config.is.not.defined");
        }
    }

}
